package cn.hn.monkey.stock.data;

import static cn.hn.monkey.stock.data.UtilsData.isTradeDay;

import android.os.Environment;
import android.os.Handler;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;

import cn.hn.monkey.stock.MainActivity;

public class DaysData {

    public static DaysData getInstance() {
        if (instance == null) {
            instance = new DaysData();
        }
        return instance;
    }

    private static DaysData instance = null;
    final String TAG = "DaysData";

    private DaysData() {

    }

    public class DayDataItem {
        int date;
        float open;
        float high;
        float low;
        float close;
        float amount;
        float volume;
        float average;  // 平均价
        float amplitude;  // 振幅

        public DayDataItem(int date, float open, float high, float low, float close, float amount, float volume) {
            this.date = date;
            this.open = open;
            this.high = high;
            this.low = low;
            this.close = close;
            this.amount = amount;
            this.volume = volume;
            average = volume > 0 ? amount / volume : 0;
            amplitude = low > 0 ? (high - low) / low : 0;
        }
    }

    public class DayDataStock {
        String strStockCode;
        List<DayDataItem> dayDataItemsList = new ArrayList<DayDataItem>();
        float maxHigh;
        float minLow;
        float amount;
        float zhenfu;
        int maxIndex;
        int minIndex;

        public DayDataStock(String code) {
            strStockCode = code;
        }

        public void append(DayDataItem item) {
            dayDataItemsList.add(item);
        }

        public void removeHead() { dayDataItemsList.remove(0); }

        public int getDays() { return dayDataItemsList.size(); }
    }

    List<DayDataStock> dayDataStocksList = new ArrayList<DayDataStock>();
    String lastStockCode;
    DayDataStock lastDayDataStock;
    boolean unzipBusy, unzipFinish;
    int[] amountIndex;
    int[] zhenfuIndex;
    int lastDate = 0;

    public void UnzipBegin(final Handler handler, final int what) {
        unzipBusy = true;
        handler.sendEmptyMessage(what);
        Log.e(TAG, "UnzipBegin");
    }

    public void UnzipEnd(final Handler handler, final int what) {
        unzipBusy = false;
        unzipFinish = true;
        if(handler != null) handler.sendEmptyMessage(what);
        Log.e(TAG, "UnzipEnd");
    }

    public boolean isUnzipFinish() {
        return unzipFinish;
    }
    float maxhigh = 0;
    float minlow = 999999999;

    public void acceptDayDataForZipFile(final String filename, final byte[] buffer, final int size, final Handler handler, final int what) {
        int pos = filename.lastIndexOf('/');
        String thisStockCode = filename.substring(pos + 1, pos + 9);
        boolean isAG = UtilsData.isAG(thisStockCode);
        if(!isAG) return;
        if(lastStockCode == null || !lastStockCode.equals(thisStockCode)) {
            lastDayDataStock = new DayDataStock(thisStockCode);
            dayDataStocksList.add(lastDayDataStock);
            lastStockCode = thisStockCode;
            if(handler != null) handler.obtainMessage(what, thisStockCode).sendToTarget();
            //Log.e("DayData", "code:" + thisStockCode + ", cnt:" + dayDataStocksList.size());
        }
        int count = size / 32;
        for(int i=0; i<count; i++) {
            int start = i * 32;
            int date = ToInt(buffer, start);
            float open = ((float) ToInt(buffer, start + 4)) / 100;
            float high = ((float) ToInt(buffer, start + 8)) / 100;
            float low = ((float) ToInt(buffer, start + 12)) / 100;
            float close = ((float) ToInt(buffer, start + 16)) / 100;
            float amount = Float.intBitsToFloat(ToInt(buffer, start + 20));
            float volume = (float) ToInt(buffer, start + 24);
            if(lastDayDataStock.strStockCode.equals("sz002432")) {
                int other = ToInt(buffer, start + 28);
                if(maxhigh < high) maxhigh = high;
                if(minlow > low) minlow = low;
                Log.e(TAG, "open:" + open + ", close:" + close + ", amount:" + amount + ", other:" + other);
            }
            DayDataItem item = new DayDataItem(date, open, high, low, close, amount, volume);
            lastDayDataStock.append(item);
            if(lastDayDataStock.getDays() > 250) lastDayDataStock.removeHead();
            if(lastDate < date) lastDate = date;
            if(lastDayDataStock.strStockCode.equals("sz002432")) {
                Log.e(TAG, "maxhigh:" + maxhigh + ", minlow:" + minlow + ", zhenfu:" + ((maxhigh-minlow)/minlow*100));
            }
        }
    }

    int ToInt(byte[] data, int start) {
        int n = 0;
        int b = data[start + 3];
        if(b < 0) b += 256;
        n = b;
        b = data[start + 2];
        if(b < 0) b += 256;
        n <<= 8;
        n += b;
        b = data[start + 1];
        if(b < 0) b += 256;
        n <<= 8;
        n += b;
        b = data[start];
        if(b < 0) b += 256;
        n <<= 8;
        n += b;
        return n;
    }

    public void parseZhenfu(final Handler handler, final int what) {
        if(handler == null) return;
        handler.sendEmptyMessage(what);
        Calendar c = Calendar.getInstance();
        int today = c.get(Calendar.YEAR) * 10000 + (c.get(Calendar.MONTH) + 1) * 100 + c.get(Calendar.DAY_OF_MONTH);
        if(lastDate < 20220808) lastDate = 20220808;
        c.set(Calendar.YEAR, lastDate / 10000);
        c.set(Calendar.MONTH, ((lastDate / 100) % 100) - 1);
        c.set(Calendar.DAY_OF_MONTH, lastDate % 100);
        while(true) {
            int theday = c.get(Calendar.YEAR) * 10000 + (c.get(Calendar.MONTH) + 1) * 100 + c.get(Calendar.DAY_OF_MONTH);
            if(theday <= today) {
                int week = c.get(Calendar.DAY_OF_WEEK);
                Log.e(TAG, "the date:" + theday + ", week:" + week);
                if(isTradeDay(week, theday)) {
                    File file = new File(Environment.getExternalStorageDirectory(), "Clockwise/cn" + theday + ".day");
                    loadStockInformation(theday, file);
                }
                c.add(Calendar.DATE, 1);
                continue;
            }
            break;
        }
        amountIndex = new int[dayDataStocksList.size()];
        zhenfuIndex = new int[dayDataStocksList.size()];
        int i = 0, j, k;
        for(DayDataStock stock : dayDataStocksList) {
            amountIndex[i] = i;
            zhenfuIndex[i] = i;
            stock.amount = 0;
            stock.zhenfu = 0;
            stock.maxHigh = 0;
            stock.minLow = 999999999;
            stock.maxIndex = 0;
            stock.minIndex = 0;
            j = 0;
            for(DayDataItem item : stock.dayDataItemsList) {
                stock.amount += item.amount;
                if(stock.maxHigh < item.high) {
                    stock.maxHigh = item.high;
                    stock.minIndex = j;
                }
                if(stock.minLow > item.low) {
                    stock.minLow = item.low;
                    stock.minIndex = j;
                }
                j ++;
            }
            if(stock.minLow > 0) stock.zhenfu = (stock.maxHigh - stock.minLow) * 100 / stock.minLow;
            i ++;
            if(stock.strStockCode.equals("sz002432")) {
                Log.e(TAG, "maxhigh:" + stock.maxHigh + ", minlow:" + stock.minLow + ", zhenfu:" + stock.zhenfu);
            }
        }
        Log.e(TAG, "Sort begin");
        for(i=0; i<dayDataStocksList.size(); i++) {
            for(j=i+1; j<dayDataStocksList.size(); j++) {
                if(dayDataStocksList.get(amountIndex[i]).amount < dayDataStocksList.get(amountIndex[j]).amount) {
                    k = amountIndex[i];
                    amountIndex[i] = amountIndex[j];
                    amountIndex[j] = k;
                }
                if(dayDataStocksList.get(zhenfuIndex[i]).zhenfu < dayDataStocksList.get(zhenfuIndex[j]).zhenfu) {
                    k = zhenfuIndex[i];
                    zhenfuIndex[i] = zhenfuIndex[j];
                    zhenfuIndex[j] = k;
                }
            }
            if(handler != null) handler.obtainMessage(what, dayDataStocksList.get(zhenfuIndex[i]).strStockCode).sendToTarget();
            //Log.e(TAG, "i:" + i + ", code:" + dayDataStocksList.get(zhenfuIndex[i]).strStockCode + ", zhenfu:" + dayDataStocksList.get(zhenfuIndex[i]).zhenfu);
        }
        Log.e(TAG, "Sort end");
    }

    void loadStockInformation(int date, File theFile) {
        boolean exist = theFile.exists();
        Log.e(TAG, "loadStockInformation, date:" + date + ", exist:" + exist);
        if(exist) {
            FileInputStream fis;
            ObjectInputStream ois;
            try {
                fis = new FileInputStream(theFile);
                ois = new ObjectInputStream(fis);
                SaveData.StockDetail[] obj = (SaveData.StockDetail[]) ois.readObject();
                List<SaveData.StockDetail> temp = Arrays.asList(obj);
                fis.close();
                for(SaveData.StockDetail sd : temp) {
                    for(DayDataStock stock : dayDataStocksList) {
                        if(stock.strStockCode.equals(sd.symbol)) {
                            DayDataItem item = new DayDataItem(date, sd.open, sd.high, sd.low, sd.trade, sd.amount, sd.volume);
                            stock.append(item);
                            while(stock.getDays() > 250) stock.removeHead();
                            //Log.e(TAG, "code:" + stock.strStockCode + ", days:" + stock.getDays());
                            break;
                        }
                    }
                }
                Log.e(TAG, "loadStockInformation, fileName:" + theFile.getAbsolutePath());
            } catch (Exception e) {
                Log.e(TAG, "loadStockInformation, fails");
                e.printStackTrace();
            }
        }
    }

    public List<DayDataStock> getStockList(int count) {
        List<DayDataStock> list = new ArrayList<DayDataStock>();
        /*
        for(int i=0,j=0; j<count; i++) {
            DayDataStock stock = dayDataStocksList.get(amountIndex[i]);
            if(stock.getDays() == 250) {
                j ++;
                Log.e(TAG, "idx:" + j + ", code:" + stock.strStockCode + ", amount:" + stock.amount / 100000000);
                list.add(stock);
            }
        }
         */
        if(dayDataStocksList.size() > 0)
        for(int i=0,j=0; j<count; i++) {
            DayDataStock stock = dayDataStocksList.get(zhenfuIndex[i]);
            if(stock.getDays() == 250) {
                j ++;
                Log.e(TAG, "idx:" + j + ", code:" + stock.strStockCode + ", maxHigh:" + stock.maxHigh + ", minLow:" + stock.minLow + ", zhenfu:" + stock.zhenfu + ", amount:" + (stock.amount / 100000000));
                list.add(stock);
            }
        }
        Log.e(TAG, "getStockList size:" + list.size());
        return list;
    }
}
